home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
Other Langs
/
MacPerl ƒ
/
Perl Source ƒ
/
MacPerl
/
MPScript.c
< prev
next >
Wrap
Text File
|
1993-12-12
|
15KB
|
823 lines
/*********************************************************************
Project : MacPerl - Real Perl Application
File : MPScript.c - Handle scripts
Author : Matthias Neeracher
Started : 16Aug93 Language : MPW C
Modified : 17Aug93 MN Set up correct default directory
14Oct93 MN Run front window
Last : 14Oct93
*********************************************************************/
#include <AERegistry.h>
#include <String.h>
#include <TFileSpec.h>
#include <setjmp.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <Signal.h>
#include <StandardFile.h>
#include <Resources.h>
#include <PLStringFuncs.h>
#include <SysEqu.h>
#include "MPScript.h"
#include "MPWindow.h"
#include "MPAppleEvents.h"
int run_perl(int, char **, char **);
void reenter();
extern Handle PerlReply;
extern int PerlQuit;
extern char gPseudoFileName[];
#ifndef RUNTIME
pascal Boolean GetScriptFilter(ParmBlkPtr info, void * data)
{
#pragma unused(data)
#else
pascal Boolean GetScriptFilter(ParmBlkPtr info)
{
#endif
switch (info->fileParam.ioFlFndrInfo.fdType) {
case 'APPL':
switch (info->fileParam.ioFlFndrInfo.fdCreator) {
case MPRtSig:
return false;
case MPAppSig:
return !info->fileParam.ioFlLgLen;
default:
return true;
}
case 'TEXT':
return false;
default:
return true;
}
}
#ifndef RUNTIME
#define gsDebugItem 10
pascal short GetScriptHook(short item, DialogPtr dlg, void * params)
{
short kind;
ControlHandle dbg;
Rect r;
Boolean * par = (Boolean *) params;
if (GetWRefCon(dlg) != 'stdf')
return item;
switch (item) {
case sfHookFirstCall:
*par = false;
return sfHookFirstCall;
case gsDebugItem:
*par = !*par;
GetDItem(dlg, item, &kind, (Handle *) &dbg, &r);
SetCtlValue(dbg, *par);
return sfHookNullEvent;
default:
return item;
}
}
static void SendScriptEvent(
DescType argType,
Ptr argPtr,
Handle argHdl,
Size argSize,
Boolean debug)
{
OSErr err;
AppleEvent cmd, repl;
AEAddressDesc addr;
if (err = MakeSelfAddress(&addr))
goto failedAddress;
if (err =
AECreateAppleEvent(
kAEMiscStandards, kAEDoScript, &addr,
kAutoGenerateReturnID, kAnyTransactionID,
&cmd)
)
goto failedAppleEvent;
if (argHdl) {
HLock(argHdl);
argPtr = *argHdl;
}
if (err = AEPutParamPtr(&cmd, keyDirectObject, argType, argPtr, argSize))
goto failedParam;
if (debug)
if (err =
AEPutParamPtr(
&cmd, 'DEBG',
typeBoolean, (Ptr) &debug, sizeof(Boolean))
)
goto failedParam;
err =
AESend(
&cmd,
&repl,
kAENoReply+kAEAlwaysInteract,
kAENormalPriority,
kAEDefaultTimeout,
nil,
nil);
AEDisposeDesc(&repl);
failedParam:
if (argHdl)
HUnlock(argHdl);
AEDisposeDesc(&cmd);
failedAppleEvent:
AEDisposeDesc(&addr);
failedAddress:
;
}
static SFTypeList PerlFileTypes = {'TEXT', 'APPL'};
pascal void DoScriptMenu(short theItem)
{
StandardFileReply reply;
Point where;
Boolean debug;
where.h = where.v = -1;
switch (theItem) {
case pmRun:
CustomGetFile(
GetScriptFilter,
2,
PerlFileTypes,
&reply,
GetScriptDialog,
where,
GetScriptHook,
(ModalFilterYDProcPtr) nil,
nil,
(ActivateYDProcPtr) nil,
&debug);
if (reply.sfGood)
SendScriptEvent(typeFSS, (Ptr) &reply.sfFile, nil, sizeof(FSSpec), debug);
break;
case pmRunFront:
{
DPtr doc = DPtrFromWindowPtr(FrontWindow());
if (!doc || doc->kind != kDocumentWindow)
break;
if (doc->dirty || !doc->u.reg.everSaved) {
if (doc->u.reg.everSaved)
strcpy(gPseudoFileName, FSp2FullPath(&doc->theFSSpec));
else
getwtitle(FrontWindow(), gPseudoFileName);
SendScriptEvent(
typeChar, nil, (*doc->theText)->hText,
GetHandleSize((*doc->theText)->hText),
false);
} else
SendScriptEvent(typeFSS, (Ptr) &doc->theFSSpec, nil, sizeof(FSSpec), false);
}
break;
}
}
#endif
static char * PerlArgs[] = {
"MacPerl",
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
};
static char * PerlEnviron[] = {
"PERLDB=require \"macperldb.pl\"",
0,
0
};
extern char * perldbgname;
pascal void InitPerlEnviron()
{
char ** env = PerlEnviron;
char * eq;
while (*env)
if (eq = strchr(*env++, '='))
*eq = 0;
perldbgname = "Dev:Console:Debug Log";
}
char * getenv(char * var)
{
char ** env;
for (env = PerlEnviron; *env; ++env)
if (!strcmp(*env, var))
return *env + strlen(*env) + 1;
return nil;
}
static jmp_buf ExitPerl;
void real_exit(int status);
void exit(int status)
{
if (gRunningPerl)
longjmp(ExitPerl, -status);
else
real_exit(status);
}
typedef void (*atexitfn)();
static atexitfn PerlExitFn[20];
static int PerlExitCnt;
int real_atexit(atexitfn func);
int atexit(atexitfn func)
{
if (gRunningPerl)
PerlExitFn[PerlExitCnt++] = func;
else
return real_atexit(func);
return 0;
}
void CleanupPerl()
{
int i;
extern FILE * _lastbuf;
UseResFile(gAppFile);
// Borrowed from GUSI
// Close stdio files (necessary to flush buffers)
// This implementation is not nice, but who cares ?
// In case you wonder, _iob is defined in <stdio.h>
for (i = 0; _iob+i<_lastbuf; i++)
fflush(_iob+i);
for (i = 0; _iob+i<_lastbuf; i++)
fclose(_iob+i);
// Close all files
for (i = 0; i<FD_SETSIZE; ++i)
close(i);
while (PerlExitCnt)
PerlExitFn[--PerlExitCnt]();
UseResFile(gAppFile);
reenter();
open("Dev:Console", O_RDONLY);
open("Dev:Console", O_WRONLY);
open("Dev:Console", O_WRONLY);
fopen("Dev:Console", "r");
fopen("Dev:Console", "w");
fopen("Dev:Console", "w");
}
enum {
extractDone = -4,
extractDir = -3,
extractCpp = -2,
extractDebug = -1
};
typedef char * (*ArgExtractor)(void * data, int index);
pascal void RunScript(ArgExtractor extractor, void * data)
{
int ArgC;
short resFile;
Handle libs;
Str255 lib;
char * res;
int i;
PtrToHand("PERLLIB", &libs, 8);
resFile = CurResFile();
UseResFile(gPrefsFile);
for (ArgC = 1; ; ++ArgC) {
GetIndString(lib, LibraryPaths, ArgC);
if (!lib[0])
break;
if (ArgC > 1)
PtrAndHand(",", libs, 1);
PtrAndHand(lib+1, libs, lib[0]);
}
UseResFile(resFile);
if (PerlEnviron[1])
DisposePtr(PerlEnviron[1]);
PerlEnviron[1] = NewPtr(GetHandleSize(libs)+1);
BlockMove(*libs, PerlEnviron[1], GetHandleSize(libs));
PerlEnviron[1][GetHandleSize(libs)] = 0;
DisposeHandle(libs);
ArgC = 1;
{
char path[256];
strcpy(path, extractor(data, extractDir));
chdir(path);
}
if ((res = extractor(data, extractDebug)) && *res == 'y')
PerlArgs[ArgC++] = "-d";
if ((res = extractor(data, extractCpp)) && *res == 'y')
PerlArgs[ArgC++] = "-P";
if (res = extractor(data, 1)) {
if (gPerlPrefs.checkType && !gPseudoFile)
PerlArgs[ArgC++] = "-x";
PerlArgs[ArgC++] = res;
for (i=2; PerlArgs[ArgC] = extractor(data, i); ++i, ++ArgC);
}
extractor(data, extractDone);
gRunningPerl = true;
PerlQuit = 0;
ShowWindowStatus();
signal(SIGINT, exit);
if (!setjmp(ExitPerl))
run_perl(ArgC, PerlArgs, PerlEnviron);
CleanupPerl();
gRunningPerl = false;
if (gScriptFile != gAppFile) {
CloseResFile(gScriptFile);
gScriptFile = gAppFile;
}
ShowWindowStatus();
for (i=1; PerlArgs[i]; ++i)
DisposPtr(PerlArgs[i]);
switch (PerlQuit) {
case 2:
#ifdef RUNTIME
case 1:
#endif
gQuitting = true;
}
}
char * AEExtractor(void * data, int index)
{
DescType type;
Size size;
Boolean arg;
AppleEvent * event;
FSSpec spec;
AEKeyword keywd;
static AEDesc params = {'????', nil};
char * retarg;
char * path;
event = (AppleEvent *) data;
switch (index) {
case extractDone:
gRuntimeScript = nil;
if (params.dataHandle)
AEDisposeDesc(¶ms);
return nil;
case extractDir:
if (gRuntimeScript
|| (!params.dataHandle
&& AEGetParamDesc(event, keyDirectObject, typeAEList, ¶ms))
|| AEGetNthPtr(
¶ms, 1, typeFSS, &keywd, &type,
(Ptr) &spec, sizeof(FSSpec), &size)
) {
spec.vRefNum = gAppVol;
spec.parID = gAppDir;
} else {
short res = CurResFile();
gScriptFile = HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
if (gPseudoFile = Get1NamedResource('TEXT', "\p!")) {
strcpy(gPseudoFileName, FSp2FullPath(&spec));
DetachResource(gPseudoFile);
}
UseResFile(res);
}
FSpUp(&spec);
return FSp2FullPath(&spec);
case extractDebug:
if (AEGetParamPtr(event, 'DEBG', typeBoolean, &type, (Ptr) &arg, 1, &size))
return nil;
else
return arg ? "y" : "n";
case extractCpp:
if (AEGetParamPtr(event, 'PREP', typeBoolean, &type, (Ptr) &arg, 1, &size))
return nil;
else
return arg ? "y" : "n";
default:
if (gRuntimeScript)
--index;
else if (index == 1 && gPseudoFile)
return "Dev:Pseudo";
if (!index) {
gPseudoFile = gRuntimeScript;
return "Dev:Pseudo";
}
if (!params.dataHandle)
if (AEGetParamDesc(event, keyDirectObject, typeAEList, ¶ms))
return nil;
if (AEGetNthPtr(
¶ms, index, typeFSS,
&keywd, &type,
(Ptr) &spec, sizeof(FSSpec), &size)
) if (index == 1 && !gRuntimeScript) {
AEDesc script;
if (AEGetNthDesc(¶ms, index, typeChar, &keywd, &script))
return nil;
gPseudoFile = script.dataHandle;
if (!gPseudoFileName[0])
strcpy(gPseudoFileName, "<AppleEvent>");
return "Dev:Pseudo";
} else if (AEGetNthPtr(
¶ms, index, typeChar,
&keywd, &type,
nil, 0, &size)
)
return nil;
else {
retarg = NewPtr(size+1);
retarg[size] = 0;
if (AEGetNthPtr(
¶ms, index, typeChar,
&keywd, &type,
retarg, size, &size)
) {
DisposPtr(retarg);
return nil;
} else
return retarg;
}
path = FSp2FullPath(&spec);
retarg = NewPtr(strlen(path)+1);
strcpy(retarg, path);
return retarg;
}
}
char * StupidExtractor(void * data, int index)
{
FSSpec * spec;
FSSpec dir;
char * retarg;
char * path;
spec = (FSSpec *) data;
switch (index) {
case extractDone:
case extractDebug:
case extractCpp:
return nil;
case extractDir:
dir = *spec;
{
short res = CurResFile();
gScriptFile = HOpenResFile(dir.vRefNum, dir.parID, dir.name, fsRdPerm);
if (gPseudoFile = Get1NamedResource('TEXT', "\p!")) {
strcpy(gPseudoFileName, FSp2FullPath(spec));
DetachResource(gPseudoFile);
}
UseResFile(res);
}
FSpUp(&dir);
return FSp2FullPath(&dir);
default:
if (index > 1)
return nil;
if (gPseudoFile)
return "Dev:Pseudo";
path = FSp2FullPath(spec);
retarg = NewPtr(strlen(path)+1);
strcpy(retarg, path);
return retarg;
}
}
char * YeOldeExtractor(void * data, int index)
{
long count;
char * retarg;
char * path;
FSSpec spec;
AppFile arg;
count = (long) data;
switch (index) {
case extractDone:
gRuntimeScript = nil;
case extractDebug:
case extractCpp:
return nil;
case extractDir:
if (gRuntimeScript) {
spec.vRefNum = gAppVol;
spec.parID = gAppDir;
} else {
short res = CurResFile();
GetAppFiles(1, &arg);
WD2FSSpec(arg.vRefNum, arg.fName, &spec);
gScriptFile = HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
if (gPseudoFile = Get1NamedResource('TEXT', "\p!")) {
strcpy(gPseudoFileName, FSp2FullPath(&spec));
DetachResource(gPseudoFile);
}
UseResFile(res);
}
FSpUp(&spec);
return FSp2FullPath(&spec);
default:
if (index - (gRuntimeScript != 0) > count)
return nil;
if (gRuntimeScript)
--index;
else if (index == 1 && gPseudoFile)
return "Dev:Pseudo";
if (!index) {
gPseudoFile = gRuntimeScript;
return "Dev:Pseudo";
}
GetAppFiles(index, &arg);
WD2FSSpec(arg.vRefNum, arg.fName, &spec);
path = FSp2FullPath(&spec);
retarg = NewPtr(strlen(path)+1);
strcpy(retarg, path);
return retarg;
}
}
pascal OSErr DoScript(const AppleEvent *event, AppleEvent *reply, long refCon)
{
#pragma unused (refCon)
if (gRunningPerl) {
const AppleEvent * e[2];
e[0] = event;
e[1] = reply;
PtrAndHand((Ptr) e, (Handle) gWaitingScripts, 8);
return AESuspendTheCurrentEvent(event);
}
RunScript(AEExtractor, event);
if (PerlReply) {
HLock(PerlReply);
AEPutParamPtr(
reply, keyDirectObject,
typeChar, *PerlReply, GetHandleSize(PerlReply));
DisposeHandle(PerlReply);
PerlReply = nil;
}
return noErr;
}
#ifdef RUNTIME
pascal void DoScriptMenu(short theItem)
{
switch (theItem) {
case pmRun:
{
Point wh;
SFTypeList types;
SFReply reply;
FSSpec spec;
wh.h = wh.v = 75;
types[0] = 'TEXT';
types[1] = 'APPL';
SFGetFile(wh, "", GetScriptFilter, 2, types, (DlgHookProcPtr) nil, &reply);
if (reply.good) {
WD2FSSpec(reply.vRefNum, reply.fName, &spec);
RunScript(StupidExtractor, &spec);
}
}
break;
case pmRunFront:
{
DPtr doc = DPtrFromWindowPtr(FrontWindow());
if (!doc || doc->kind != kDocumentWindow)
break;
if (doc->dirty || !doc->u.reg.everSaved) {
gRuntimeScript = (*doc->theText)->hText;
HandToHand(&gRuntimeScript);
if (doc->u.reg.everSaved)
strcpy(gPseudoFileName, FSp2FullPath(&doc->theFSSpec));
else
getwtitle(FrontWindow(), gPseudoFileName);
RunScript(YeOldeExtractor, (void *) 0);
} else
RunScript(StupidExtractor, &doc->theFSSpec);
}
break;
}
}
#endif
pascal Boolean DoRuntime()
{
short message;
short count;
FSSpec spec;
if (gRuntimeScript = Get1NamedResource('TEXT', "\p!")) {
spec.vRefNum = gAppVol;
spec.parID = gAppDir;
PLstrcpy(spec.name, (StringPtr) CurApName);
strcpy(gPseudoFileName, FSp2FullPath(&spec));
DetachResource(gRuntimeScript);
}
#ifndef RUNTIME
return false;
#else
if (gAppleEventsImplemented)
return false;
CountAppFiles(&message, &count);
if (count) {
if (message == appPrint) {
int i;
AppFile arg;
for (i=0; i++<count; ) {
GetAppFiles(i, &arg);
WD2FSSpec(arg.vRefNum, arg.fName, &spec);
if (!IssueAEOpenDoc(spec)) {
IssuePrintWindow(FrontWindow());
IssueCloseCommand(FrontWindow());
}
}
return true;
}
} else {
if (!gRuntimeScript) {
int i;
AppFile arg;
for (i=0; i++<count; ) {
GetAppFiles(i, &arg);
WD2FSSpec(arg.vRefNum, arg.fName, &spec);
IssueAEOpenDoc(spec);
}
return false;
}
}
RunScript(YeOldeExtractor, (void *) count);
return gQuitting;
#endif
}